package pers.wchen.mybatis.generate.data;

import com.google.gson.Gson;
import pers.wchen.mybatis.generate.data.database.BaseDatabase;
import pers.wchen.mybatis.generate.data.database.MysqlFactory;
import pers.wchen.mybatis.generate.data.property.PropertyManager;
import pers.wchen.mybatis.generate.model.DataComposeVO;
import pers.wchen.mybatis.generate.model.DatabaseTablePropertyVO;
import pers.wchen.mybatis.generate.model.FileInfoVO;
import pers.wchen.mybatis.generate.util.CharsTransUtil;

import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @作者： wchen
 * @描述： 数据库表数据管理
 * @创建时间： 2018/2/9 14:03
 * @版本：Copyright 2018, Inc. All Rights Reserved.
 * @修改信息：
 */
public class DataManager {

    private String propertyPath;
    private BaseDatabase baseDatabase;
    private Map<String, String> configMap;
    private String[] queryTableNames;

    /**
     *  @描述: 获取所有表相关的信息
     *  @参数： []
     *  @返回值： java.util.Map<java.lang.String,pers.wchen.mybatis.generate.model.DataComposeVO>
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public Map<String, DataComposeVO>  getDataInfo(){

        Map<String, DataComposeVO> dataMap = new HashMap<String, DataComposeVO>();
        //表字段map
        Map<String, List<DatabaseTablePropertyVO>> tablePropertyMap = getTableFieldInfo();
        //表级注释map
        Map<String, String> tableComponentMap = getAllTableComponent();

        //遍历所有查询的表生成map
        for(String tableName : this.queryTableNames){
            DataComposeVO dataComposeVO = new DataComposeVO();
            dataComposeVO.setDatabaseTablePropertyVOS(tablePropertyMap.get(tableName));
            dataComposeVO.setTableComponent(tableComponentMap.get(tableName));
            dataComposeVO.setFileInfoMap(getFileInfo(tableName));
            dataComposeVO.setBuildFiles(getBuildFiles());
            dataMap.put(tableName, dataComposeVO);
        }
        return dataMap;
    }


    /**
     *  @描述: 获取要生成的文件
     *  @参数： []
     *  @返回值： java.lang.String[]
     *  @创建人: wchen
     *  @创建时间: 2018/2/10
     *  @修改人和其它信息:
     */
    private String[] getBuildFiles(){

        String[] buildFiles = getConfigMap().get("build.files").split(",");
        return buildFiles;
    }


    /**
     *  @描述: 获取文件组成相关信息
     *  @参数： [tableName]
     *  @返回值： java.util.Map<java.lang.String,pers.wchen.mybatis.generate.model.FileInfoVO>
     *  @创建人: wchen
     *  @创建时间: 2018/2/10
     *  @修改人和其它信息:
     */
    public Map<String, FileInfoVO> getFileInfo(String tableName){

        Map<String, FileInfoVO> dataMap = new HashMap();
        String transTableName = CharsTransUtil.upperCaseFist(CharsTransUtil.transParam(tableName));
        String projectPath = getConfigMap().get("project.path");
        String javaFilePath = projectPath + "java/";
        String className = transTableName + "VO";

        //vo
        String packagePath = getConfigMap().get("project.package.vo");
        if(packagePath != null || !packagePath.equals("")) {
            FileInfoVO voFileInfo = new FileInfoVO();
            voFileInfo.setFileName(className + ".java");
            voFileInfo.setClassName(className);
            voFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            voFileInfo.setPackageName(packagePath);
            voFileInfo.setFilePath(javaFilePath + packagePath.replace(".", "\\") + "\\" + className + ".java");
            dataMap.put("vo", voFileInfo);
        }
        //controller
        packagePath = getConfigMap().get("project.package.controller");
        if(packagePath != null || !packagePath.equals("")) {
            className = transTableName + "Controller";
            FileInfoVO controllerFileInfo = new FileInfoVO();
            controllerFileInfo.setFileName(className + ".java");
            controllerFileInfo.setClassName(className);
            controllerFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            controllerFileInfo.setPackageName(packagePath);
            controllerFileInfo.setFilePath(javaFilePath + packagePath.replace(".", "\\") + "\\" + className + ".java");
            dataMap.put("controller", controllerFileInfo);
        }
        //dao
        packagePath = getConfigMap().get("project.package.dao");
        if(packagePath != null || !packagePath.equals("")) {
            className = transTableName + "Mapper";
            FileInfoVO mapperFileInfo = new FileInfoVO();
            mapperFileInfo.setFileName(className + ".java");
            mapperFileInfo.setClassName(className);
            mapperFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            mapperFileInfo.setPackageName(packagePath);
            mapperFileInfo.setFilePath(javaFilePath + packagePath.replace(".", "\\") + "\\" + className + ".java");
            dataMap.put("dao", mapperFileInfo);
        }
        //service
        packagePath = getConfigMap().get("project.package.service");
        if(packagePath != null || !packagePath.equals("")) {
            className = transTableName + "Service";
            FileInfoVO serviceFileInfo = new FileInfoVO();
            serviceFileInfo.setFileName(className + ".java");
            serviceFileInfo.setClassName(className);
            serviceFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            serviceFileInfo.setPackageName(packagePath);
            serviceFileInfo.setFilePath(javaFilePath + packagePath.replace(".", "\\") + "\\" + className + ".java");
            dataMap.put("service", serviceFileInfo);
        }
        //serviceImpl
        packagePath = getConfigMap().get("project.package.serviceImpl");
        if(packagePath != null || !packagePath.equals("")) {
            className = transTableName + "ServiceImpl";
            FileInfoVO serviceImplFileInfo = new FileInfoVO();
            serviceImplFileInfo.setFileName(className + ".java");
            serviceImplFileInfo.setClassName(className);
            serviceImplFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            serviceImplFileInfo.setPackageName(packagePath);
            serviceImplFileInfo.setFilePath(javaFilePath + packagePath.replace(".", "\\") + "\\" + className + ".java");
            dataMap.put("serviceImpl", serviceImplFileInfo);
        }
        //test
        packagePath = getConfigMap().get("project.package.test");
        if(packagePath != null || !packagePath.equals("")) {
            className = transTableName + "ControllerTest";
            FileInfoVO testFileInfo = new FileInfoVO();
            testFileInfo.setFileName(className + ".java");
            testFileInfo.setClassName(className);
            testFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            testFileInfo.setPackageName(packagePath);
            testFileInfo.setFilePath(javaFilePath + packagePath.replace(".", "\\") + "\\" + className + ".java");
            dataMap.put("test", testFileInfo);
        }
        //xml特殊处理需要用到mapper的package
        packagePath = getConfigMap().get("project.package.xml");
        if(packagePath != null || !packagePath.equals("")) {
            String daoPackage = dataMap.get("dao").getPackageName() + "." + dataMap.get("dao").getClassName();
            className = transTableName + "Mapper";
            FileInfoVO xmlFileInfo = new FileInfoVO();
            xmlFileInfo.setFileName(className);
            xmlFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            xmlFileInfo.setPackageName(daoPackage);
            xmlFileInfo.setFilePath(projectPath + packagePath.replace(".", "\\") + "\\" + className + ".xml");
            dataMap.put("xml", xmlFileInfo);
        }
        //view处理
        packagePath = getConfigMap().get("project.package.view");
        if(packagePath != null || !packagePath.equals("")) {
            className = transTableName + ".ftl";
            FileInfoVO xmlFileInfo = new FileInfoVO();
            xmlFileInfo.setFileName(className);
            xmlFileInfo.setLowerClassName(CharsTransUtil.lowerCaseFist(className));
            xmlFileInfo.setFilePath(projectPath + packagePath.replace(".", "\\") + "\\" + className);
            dataMap.put("view", xmlFileInfo);
        }

        return dataMap;
    }


    /**
     *  @描述: 获取表级注释
     *  @参数： []
     *  @返回值： java.util.Map<java.lang.String,java.lang.String>
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public Map<String, String> getAllTableComponent(){
        //sql拼装
        String[] queryTables = getQueryTableNames();
        StringBuffer sbf = new StringBuffer();
        for(int i=0; i<queryTables.length; i++){
            sbf.append("'").append(queryTables[i]).append("'");
            if(i < queryTables.length-1){
                sbf.append(",");
            }
        }
        String querySql = getConfigMap().get("dataSource.queryTableComponent").replace("&{tableName}", sbf.toString());
        System.out.println("querySql :");
        System.out.println(querySql);
        //查询注释
        Map<String, String> componentMap = getBaseDatabase().getOtherInfo(querySql);
        return componentMap;
    }


    /**
     *  @描述: 获取表的字段信息map
     *  @参数： []
     *  @返回值： java.util.Map<java.lang.String,java.util.List<pers.wchen.mybatis.generate.model.DatabaseTablePropertyVO>>
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public Map<String, List<DatabaseTablePropertyVO>> getTableFieldInfo(){

        String preQuerySql = getConfigMap().get("dataSource.querySql");
        String[] queryTables = getQueryTableNames();
        Map<String, List<DatabaseTablePropertyVO>> dataMap = new HashMap<String, List<DatabaseTablePropertyVO>>();
        for(String tableName : queryTables){
            List<DatabaseTablePropertyVO> tablePropertyVOS = getBaseDatabase().getDatabaseData(preQuerySql.replace("&{tableName}", tableName));
            dataMap.put(tableName, tablePropertyVOS);
        }
        return dataMap;
    }


    /**
     *  @描述: 获取要操作的所有表名称
     *  @参数： []
     *  @返回值： java.lang.String[]
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public String[] getQueryTableNames() {

        if(this.queryTableNames == null || this.queryTableNames.length == 0){
            String[] tableNames = getConfigMap().get("dataSource.queryTableName").split(",");
            this.queryTableNames = tableNames;
            return tableNames;
        }

        return queryTableNames;
    }

    /**
     *  @描述: 获取配置信息(重写)
     *  @参数： []
     *  @返回值： java.util.Map<java.lang.String,java.lang.String>
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public Map<String, String> getConfigMap() {
        if(this.configMap == null){
            Map queryConfigMap = PropertyManager.newInstance().getConfigMap(getPropertyPath());
            this.configMap = queryConfigMap;
        }
        return configMap;
    }

    /**
     *  @描述: 获取BaseDatabase，默认mysql
     *  @参数： []
     *  @返回值： pers.wchen.mybatis.generate.data.database.BaseDatabase
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public BaseDatabase getBaseDatabase() {
        if(baseDatabase == null){
            Map<String, String> configMap = getConfigMap();
            BaseDatabase database = new MysqlFactory(
                    configMap.get("datasource.url"),
                    configMap.get("datasource.driverName"),
                    configMap.get("datasource.username"),
                    configMap.get("datasource.password")
            );
            this.baseDatabase = database;
            return database;
        }
        return baseDatabase;
    }


    /**
     *  @描述: 获取数据库配置路径
     *  @参数： []
     *  @返回值： java.lang.String
     *  @创建人: wchen
     *  @创建时间: 2018/2/9
     *  @修改人和其它信息:
     */
    public String getPropertyPath() {
        if(propertyPath == null || propertyPath.trim().equals("")){
            try {
                String defaultPropertyPath = this.getClass().getClassLoader().getResource("").toURI().getPath() + "config/database.properties";
                this.propertyPath = defaultPropertyPath;
                return defaultPropertyPath;
            }catch (URISyntaxException e){
                e.printStackTrace();
            }
        }
        return propertyPath;
    }

    public void setPropertyPath(String propertyPath) {
        this.propertyPath = propertyPath;
    }


    public void setBaseDatabase(BaseDatabase baseDatabase) {
        this.baseDatabase = baseDatabase;
    }
}
